#include "head.h"
#include "tcp.h"

#define MAX_SECS_TO_LINGER 15

int INET_Connect(int port,char *address)
{
	int sockfd=0;
	int n;
	struct sockaddr_in srv_addr;
	int rcvbuf=8192;

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<=0){
		perror("SOCKET ERROR");
		return(-1);
	}
	memset(&srv_addr,0,sizeof(struct sockaddr_in));

	srv_addr.sin_family=AF_INET;
	srv_addr.sin_port=htons(port);
	srv_addr.sin_addr.s_addr=inet_addr(address);

	if(connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(struct sockaddr_in)
	)<0){
		perror("Connect Error");
		close(sockfd);
		return(-1);
	}
	return(sockfd);
}


int UNIX_Connect(char *filename)
{
	int sockfd=0;
	struct sockaddr_un srv_addr;

	if((sockfd=socket(AF_UNIX,SOCK_STREAM,0))<0){
		perror("SOCKET ERROR");
		return -1;
	}
/*	sock_enable_linger(sockfd);*/
	srv_addr.sun_family=AF_UNIX;
	strcpy(srv_addr.sun_path,filename);
	if(connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr.sun_family)+strlen(srv_addr.sun_path))<0){
		perror("Connect Error");
		close(sockfd);
		return -1;
	}

	return(sockfd);
}

int INET_Listen(int Port)
{
	int 	sockfd=0;
	struct 	sockaddr_in srv_addr;
	pid_t 	pid;
	int 	mss=1024;
	int 	len=sizeof(int);

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
		perror("SOCKET ERROR");
		return -1;
	}
	if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&mss,len)<0){
		perror("[ERROR]:setsockopt");
		close(sockfd);
		return -1;
	}
	/*sock_enable_linger(sockfd);*/
	memset(&srv_addr,0x00,sizeof(struct sockaddr_in));
	srv_addr.sin_family=AF_INET;
	srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	srv_addr.sin_port=htons(Port);
	if(bind(sockfd,(struct sockaddr *)&srv_addr,sizeof(struct sockaddr_in))!=0){
		perror("bind error");
		close(sockfd);
		return -1;
	}
	if(listen(sockfd,75)<0)
	{
		perror("listen");
		close(sockfd);
		return -1;
	}
	return(sockfd);
}
int UNIX_Listen(char *filename)
{
	int 	sockfd=0;
	struct 	sockaddr_un srv_addr;

	if((sockfd=socket(AF_UNIX,SOCK_STREAM,0))<0){
		perror("SOCKET ERROR");
		return -1;
	}
	/*sock_enable_linger(sockfd);*/
	srv_addr.sun_family=AF_UNIX;
	strcpy(srv_addr.sun_path,filename);
	unlink(filename);
	if(bind(sockfd,(struct sockaddr *)&srv_addr,
	sizeof(srv_addr.sun_family)+strlen(srv_addr.sun_path))){
		perror("bind error");
		close(sockfd);
		unlink(filename);
		return -1;
	}

	if(listen(sockfd,75)<0)
	{
		perror("listen");
		close(sockfd);
		return -1;
	}

	return(sockfd);
}


int UDP_Connect(int port,char *address)
{
       int sockfd=0;
       int n;
       struct sockaddr_in srv_addr;
       int rcvbuf=8192;

       if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<=0){
               perror("SOCKET ERROR");
               return(-1);
       }
       memset(&srv_addr,0,sizeof(struct sockaddr_in));
       if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))<0)
       {
               perror("SOCKET ERROR");
               close(sockfd);
               return -1;
       }
       if (setsockopt(sockfd, SOL_SOCKET, SO_RCVLOWAT, &rcvbuf, sizeof(rcvbuf))<0)
       {

               perror("setsockopt");
               close(sockfd);
               return -1;
       }
       srv_addr.sin_family=AF_INET;
       srv_addr.sin_port=htons(port);
       srv_addr.sin_addr.s_addr=inet_addr(address);

       if(connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(struct sockaddr_in))<0)
       {
               perror("connect");
               close(sockfd);
               return(-1);
       }
       return(sockfd);
}


int UDP_Listen(int Port)
{
       int     sockfd=0;
       struct  sockaddr_in srv_addr;
       pid_t   pid;
       int     mss=1024;
       int     len=sizeof(int);
       int     n;

       if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0){
               perror("socke");
               return -1;
       }
       if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&mss,len)<0){
               perror("setsockopt");
               close(sockfd);
               return -1;
       }

       memset(&srv_addr,0x00,sizeof(struct sockaddr_in));
       srv_addr.sin_family=AF_INET;
       srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
       srv_addr.sin_port=htons(Port);

       if(bind(sockfd,(struct sockaddr *)&srv_addr,sizeof(struct sockaddr_in))!=0){
               perror("bind");
               close(sockfd);
               return -1;
       }
       return(sockfd);
}

int Server_GetCommSock(int iDomain,int iListenFd)
{
	int sockfd=0;
	int rcvbuf=1;

	if(iDomain==AF_INET) {
		sockfd=accept(iListenFd, NULL,NULL);
		if(sockfd<0)
		{
			perror("accept");
			close(sockfd);
			return -1;
		}
		/*sock_enable_linger(sockfd);*/
		return sockfd;
	}
	else if	(iDomain==AF_UNIX) {
		sockfd=accept(iListenFd,NULL,NULL );
		if(sockfd<0)
		{
			perror("accept");
			close(sockfd);
			return -1;
		}
		/*sock_enable_linger(sockfd);*/
			if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &rcvbuf, sizeof(rcvbuf))<0) {
		perror("setsockopt:SO_RECVBUF");
		close(sockfd);
		return -1;
	}
	if (setsockopt(sockfd, SOL_SOCKET, SO_SNDLOWAT, &rcvbuf, sizeof(rcvbuf))<0) {
		perror("setsockopt:SO_RCVLOWAT");
		close(sockfd);
		return -1;
	}
		return sockfd;
	}
}
